/*
Copyright (c) 2009, Luke Berndt
All rights reserved.
 
 * More Information: http://www.tagflo.com

Redistribution and use in source and binary forms, with or without modification, are permitted 
provided that the following conditions are met:

* Redistributions of source code must retain the above copyright notice, this list of conditions 
  and the following disclaimer.

* Redistributions in binary form must reproduce the above copyright notice, this list of conditions 
  and the following disclaimer in the documentation and/or other materials provided with the distribution.

* Neither the name of RoboTastic Software nor the names of its contributors may be used to endorse or 
  promote products derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED 
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
POSSIBILITY OF SUCH DAMAGE.
*/


using System;
using System.Linq;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Text;
using System.Data;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.ComponentModel;

namespace TagFlo
{
    /// <summary>
    /// Interaction logic for SetListBox.xaml
    /// </summary>


    /// <summary>
    /// This class represents the items that appear in the Set List Box. Each item has a thumbnail and a path
    /// </summary>

    public class SetListBoxItem
    {
        string path;
        byte[] thumbnail;

        public SetListBoxItem(DataRowView row)
        {
            path = row["Path"].ToString();
            thumbnail = (byte[])row["Thumbnail"];
        }

        public byte[] Thumbnail
        {
            get { return thumbnail; }
        }

        public string Path { get { return path; } }

    }

    /// <summary>
    /// This class extends the ListBox to create a SetListBox
    /// </summary>
    public partial class SetListBox : ListBox
    {

        public static readonly RoutedEvent PhotoSetChangeEvent =
       EventManager.RegisterRoutedEvent("PhotoSetChange",
                                       RoutingStrategy.Bubble,
                                       typeof(RoutedEventHandler),
                                       typeof(SetListBox));



        public event RoutedEventHandler PhotoSetChange
        {
            add { AddHandler(PhotoSetChangeEvent, value); }
            remove { RemoveHandler(PhotoSetChangeEvent, value); }
        }
        // PhotoList stores the thumbnails for the listbox
        private ThreadedObservableCollection<Photo> photoCollection;
        private ThreadedObservableCollection<PhotoSet> photoSetCollection;

        PhotoDBEntities photoEntities = new PhotoDBEntities();
        
        // The name for the current photoset name
        string currentPhotoSetName = null;
        PhotoSet currentPhotoSet = null;

        public ThreadedObservableCollection<Photo> PhotoCollection
        {
            get { return photoCollection; }
            set
            {
                photoCollection = value;
            }
        }

        public ThreadedObservableCollection<PhotoSet> PhotoSetCollection
        {
            get { return photoSetCollection; }
            set
            {

                photoSetCollection = value;
            }

        }
      
        /// <summary>
        /// Gets called when something gets dragged over it.
        /// It allows for gropping if it is of the DataRowView type.
        /// </summary>
        /// <param name="e"></param>
        protected override void OnDragOver(DragEventArgs e)
        {
            if (e.Data.GetDataPresent(typeof(Photo[])) && (currentPhotoSet != null))
            {
                e.Effects = DragDropEffects.Copy;
            }
            else
            {
                e.Effects = DragDropEffects.None;
            }
            base.OnDragOver(e);
            
        }

        private void UpdateSetListNames()
        {
            /*SetListNames.Clear();

            if (dataSet == null)
            {
                return;
            }

            foreach (DataRow row in dataSet.dataSet.Tables["DistinctPhotoSetTable"].Rows)
            {
                SetListNames.Add(row["PhotoSetName"].ToString());
            }*/
        }

        private Boolean NewPhotoSet(string name)
        {
            if (PhotoSetExists(name))
            {
                return false;
            }

            PhotoSet photoSet = PhotoSet.New();
            photoSet.PhotoSetName = name;

            photoEntities.AddToPhotoSets(photoSet);
            photoSetCollection.Add(photoSet);
            photoEntities.SaveChanges();
            currentPhotoSet = photoSet;

            if (currentPhotoSet.Photos.IsLoaded == false)
            {
                currentPhotoSet.Photos.Load();
            }
            this.DataContext = currentPhotoSet.Photos;

            this.RaiseEvent(new RoutedEventArgs(SetListBox.PhotoSetChangeEvent, this));
            return true;

        }

        /// <summary>
        /// Checks to see if a Photo with that path exists already in the photo set list
        /// </summary>
        /// <param name="path">The Path to check</param>
        /// <returns>True if the photo is already in the list</returns>
        private bool PhotoExists(int photoID)
        {

            return photoSetCollection.Any(ps => ps.Photos.Any(p => p.PhotoID==photoID) && ps.PhotoSetName == currentPhotoSet.PhotoSetName);

           
        }

        private bool PhotoSetExists(string name)
        {
            return photoSetCollection.Any(p => p.PhotoSetName == name);

        }

        public bool AddImage(Photo dragPhoto)
        {
            if (currentPhotoSet == null)
            {
                return false;
            }
            if (PhotoExists(dragPhoto.PhotoID) == false)
            {
                Photo photo = photoEntities.Photos.FirstOrDefault(p => p.PhotoID == dragPhoto.PhotoID);
           //     PhotoSet photoSet = photoEntities.PhotoSets.FirstOrDefault(p => p.PhotoSetID == currentPhotoSet.PhotoSetID);
                
                // Adds the file to DB
          //      photoSet.Photos.Add(photo);
                currentPhotoSet.Photos.Add(photo);
                photoEntities.SaveChanges();
                return true;
            }
            return false;
        }

        /// <summary>
        /// Gets called when a photo gets dropped
        /// </summary>
        /// <param name="e"></param>
        protected override void OnDrop(DragEventArgs e)
        {
            // Calls the underlying handler from ListBox for OnDrop
            base.OnDrop(e);

            // If DataSet has not been set yet or the current PhotoSetName has not been set, do nothing
            if (currentPhotoSet == null)
            {

                e.Effects = DragDropEffects.None;

                return;
            }

            // If everything is setup and the object is the right type, process the dropped object
            if (e.Data.GetDataPresent(typeof(Photo[])))
            {
                Photo[] photos = (Photo[])e.Data.GetData(typeof(Photo[]));
                
                e.Effects = DragDropEffects.Copy;

                // Process all of the files passed 
                foreach (Photo photo in photos)
                {
                    AddImage(photo);
                      
                    
                }
             
            }
        }

        public SetListBox()
        {
            InitializeComponent();
        }

        private void OnInit(object sender, EventArgs e)
        {
            photoSetCollection = new ThreadedObservableCollection<PhotoSet>(this.Dispatcher, photoEntities.PhotoSets.Include("Photos").ToList());

            ComboBox PhotoSetComboBox = (ComboBox)this.Template.FindName("PhotoSetComboBox", this);
            PhotoSetComboBox.DataContext = photoSetCollection;
       
        }
        public void RemoveSetButton_Click(Object sender, RoutedEventArgs e)
        {
            DataRow removeRow=null;
            if (currentPhotoSetName != null)
            {
                ComboBox PhotoSetComboBox = (ComboBox)this.Template.FindName("PhotoSetComboBox", this);
            
                // Configure message box
                string message = "Do you wish to remove the Set List: " + PhotoSetComboBox.Text;
                string caption = "Remove Set List";
                MessageBoxButton buttons = MessageBoxButton.YesNo;
                // Show message box
                MessageBoxResult result = MessageBox.Show(message, caption, buttons);

                if (result == MessageBoxResult.Yes)
                {
                    if (removeRow != null)
                    {
                    }
                    this.RaiseEvent(new RoutedEventArgs(SetListBox.PhotoSetChangeEvent, this));

                    currentPhotoSetName = null;
                }
            }

        }
        public void PhotoSetComboBox_SelectionChanged(Object sender, SelectionChangedEventArgs e)
        {
            if ((e.AddedItems.Count > 0))
            {
                currentPhotoSet = (PhotoSet) e.AddedItems[0];
                if (currentPhotoSet.Photos.IsLoaded == false)
                {
                    currentPhotoSet.Photos.Load();
                }
                this.DataContext = currentPhotoSet.Photos;
            }

        }

        private void PhotoSetComboBox_PreviewKeyDown(object sender, System.Windows.Input.KeyEventArgs e)
        {
            if (e.Key == Key.Enter)
            {
                ComboBox PhotoSetComboBox = (ComboBox)this.Template.FindName("PhotoSetComboBox", this);
            
                // Configure message box
                string message = "Do you wish to create the new Set List: " + PhotoSetComboBox.Text;
                string caption = "New Set List";
                MessageBoxButton buttons = MessageBoxButton.YesNo;
                // Show message box
                MessageBoxResult result = MessageBox.Show(message, caption, buttons);

                if (result == MessageBoxResult.Yes)
                {
                    NewPhotoSet(PhotoSetComboBox.Text);
                    
                    //Keyboard.Focus(this);
                }
                else
                {
                    PhotoSetComboBox.SelectedIndex = 0;

                }
                // PhotoSetComboBox.SelectedItem = new TextBlock(new Run(currentPhotoSetName));

             


               
              
            }
        }



      
    }
}